#pragma once 

#include <function>

namespace tb {

namespace dispatch {

struct EventBus : public Singleton<EventBus> {
    typedef std::function<void (const VoidPtr &)> event_handler_type;

    typedef std::shared_ptr<Void> event_param_type;

public:
    void Post(
        const char *eventId, 
        const event_param_type &param = event_param_type(), 
        const std::string &eceiverId = "",
        int depth = INT_MAX);

    void PostBlocking(
        const char *eventId, 
        const event_param_type &param = event_param_type(), 
        const std::string &eceiverId = "",
        int depth = INT_MAX);

    void PostSticky(
        unsigned int eventCode, 
        const event_param_type &param = event_param_type());

    template <typename ClassType, typename FunctorType>
    void Sub(
        const IWoker::Ptr &wrk, 
        const char *eventId,  
        FunctorType fn, 
        ClassType obj,
        const std::string &ident = "",
        short priority = 128) {

    }

    template <typename FunctorType>
    void Sub(
        const IWoker::Ptr &wrk, 
        const char *eventId, , 
        FunctorType fn, 
        const std::string &ident = "",
        short priority = 128) {

    }

    template <typename ClassType, typename FunctorType>
    void SubSync(
        const char *eventId, , 
        FunctorType fn, 
        ClassType obj,
        const std::string &ident = "",
        short priority = 128) {
        Subscribe(NULL, eventCode, fn, obj, ident, priority);
    }

    template <typename ClassType>
    void UnSub(ClassTyep obj) {

    }

    template <typename FunctorType>
    void UnSub(
        const IWoker::Ptr &wrk, 
        unsigned int eventCode, 
        FunctorType fn) {
        
    }

    template <typename FunctorType>
    void UnSub(const std::string &ident) {
        
    }

    void UnSubAll();

    typedef std::shared_ptr<EventBus> Ptr;

    Ptr Fork();

private:
    template <typename ClassType, typename FunctorType, typename SafeObjectHandler>
    void Sub_(
        const IWorker::Ptr &wrk, 
        const char *eventId, 
        FunctorType fn, ClassType obj, 
        const SafeObjectHandler &hdl, 
        const std::string &ident = "", 
        int priority = 28);

    void UnSub_(
        const IWorker::Ptr &wrk,, 
        const char *eventId, 
        void *funPtr, 
        void *obj = NULL);

    void UnSubByObject(void *obj);

    bool IsEventSubed(
        const IWorker::Ptr &wrk,, 
        const char *eventId, 
        void *funPtr, 
        void *obj = NULL
    );

    template <typename FunctorType>
    bool IsEventSubed_(
        const IWorker::Ptr &wrk,, 
        const char *eventId, 
        FunctorType fn
    ) {
        
    }

    struct Impl;
    Impl *_impl;
};

} // end namespace dispatch

} // end namespace tb